package io.gitee.zhangbinhub.acp.cloud.resource.server.tools

import io.gitee.zhangbinhub.acp.cloud.resource.server.constant.AcpCloudResourceServerConstant
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal
import java.time.Instant

object TokenTools {
    @JvmStatic
    fun convertClaimsSet(claims: MutableMap<String, Any?>): OAuth2AuthenticatedPrincipal {
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_AUD, fun(_: String, value: Any?): Any? {
                return (value as? String)?.let { listOf(it) } ?: value
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_EXP, fun(_: String, value: Any?): Any? {
                return value?.let {
                    Instant.ofEpochSecond((it as Number).toLong())
                }
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_IAT, fun(_: String, value: Any?): Any? {
                return value?.let {
                    Instant.ofEpochSecond((it as Number).toLong())
                }
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_NBF, fun(_: String, value: Any?): Any? {
                return value?.let {
                    Instant.ofEpochSecond((it as Number).toLong())
                }
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_CLIENT_ID, fun(_: String, value: Any?): Any? {
                return value?.toString()
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_ISS, fun(_: String, value: Any?): Any? {
                return value?.toString()
            }
        )
        val authorities: MutableCollection<GrantedAuthority> = mutableListOf()
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_SCOPE, fun(_: String, value: Any?): Any? {
                return if (value !is String) {
                    value
                } else {
                    value.split(" ").onEach { scope ->
                        authorities.add(SimpleGrantedAuthority("SCOPE_$scope"))
                    }
                }
            }
        )
        claims.computeIfPresent(
            AcpCloudResourceServerConstant.TOKEN_CLAIMS_AUTHORITIES, fun(_: String, value: Any?): Any? {
                return if (value !is Collection<*>) {
                    value
                } else {
                    value.forEach { authority ->
                        authorities.add(SimpleGrantedAuthority("$authority"))
                    }
                }
            }
        )
        return OAuth2IntrospectionAuthenticatedPrincipal(claims, authorities)
    }
}